package cn.com.seederland.gkrpc.server;

import cn.com.seederland.gkrpc.Request;
import cn.com.seederland.gkrpc.Response;
import cn.com.seederland.gkrpc.codec.Decoder;
import cn.com.seederland.gkrpc.codec.Encoder;
import cn.com.seederland.gkrpc.common.constants.exception.ExceptionConstants;
import cn.com.seederland.gkrpc.common.utils.ReflectionUtils;
import cn.com.seeederland.gkrpc.transport.RequestHandler;
import cn.com.seeederland.gkrpc.transport.TransportServer;
import org.apache.commons.io.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

/**
 * @ClassName RpcServer
 * @Author SighFate
 * @Date 2020/10/07 0:33
 * @Version 1.0
 * @Description RPC服务端
 */
public class RpcServer {

    private static Logger LOGGER = LoggerFactory.getLogger(RpcServer.class);

    /**
     * 服务端配置
     */
    private ServerConfig config;
    /**
     * 网络通讯
     */
    private TransportServer transport;
    /**
     * 序列化
     */
    private Encoder encoder;
    /**
     * 反序列化
     */
    private Decoder decoder;
    /**
     * 服务管理器
     */
    private ServiceManager serviceManager;
    /**
     * 服务执行器
     */
    private ServiceInvoke serviceInvoke;

    /**
     * 请求处理
     */
    private RequestHandler requestHandler = new RequestHandler() {
        @Override
        public void onRequest(InputStream receiveData, OutputStream responseData) {
            Response response = new Response();
            try {
                byte[] requestBytes = IOUtils.readFully(receiveData, receiveData.available());

                Request request = decoder.decoder(requestBytes, Request.class);
                LOGGER.info("请求数据：{}", request.getServiceDescriptor().toString());

                ServiceInstance serviceInstance = serviceManager.lookup(request);
                Object invokeResult = serviceInvoke.invoke(serviceInstance, request);

                response.setData(invokeResult);
            } catch (Exception e) {
                LOGGER.warn("请求处理失败.", e);
                response.setCode(ExceptionConstants.HANDLER_ERROR);
                response.setMessage("服务端处理失败：" + e.getClass().getName() + " - " + e.getMessage());
            } finally {
                try {
                    byte[] resultBytes = encoder.encode(response);
                    responseData.write(resultBytes);
                    LOGGER.info("返回数据给客户端.");
                } catch (IOException e) {
                    LOGGER.warn("返回数据写入失败：", e);
                }
            }
        }
    };

    public RpcServer() {
        this(new ServerConfig());
    }

    public RpcServer(ServerConfig config) {
        this.config = config;
        this.transport = ReflectionUtils.newInstance(config.getTransPortClass());
        this.encoder = ReflectionUtils.newInstance(config.getEncoderClass());
        this.decoder = ReflectionUtils.newInstance(config.getDecoderClass());
        this.serviceManager = new ServiceManager();
        this.serviceInvoke = new ServiceInvoke();
        this.transport.init(config.getPort(), requestHandler);
    }

    /**
     * 服务注册
     * @param interfaceClass 定义的服务接口对象
     * @param bean 对象的实现类
     * @param <T> 需要注册的对象类型
     */
    public <T> void register(Class<T> interfaceClass, T bean) {
        this.serviceManager.register(interfaceClass, bean);
    }

    public void start(){
        this.transport.start();
    }

    public void stop(){
        this.transport.close();
    }
}
